package com.fangcun.common.util.date;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

/**
 * @作者： 丶CHEN、@时间： 2018年6月20日 - 上午10:11:54 @description：-> 时间工具
 */
public class DateUtils {
	 /**
     * 从Date类型的时间中提取日期部分
     */
    public static Date getDate(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTime();
    }

    /**
     * 从Date类型的时间中提取时间部分
     */
    public static Date getTime(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.YEAR, 1970);
        calendar.set(Calendar.MONTH, 0);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        return calendar.getTime();
    }
	private static Logger LOG = LoggerFactory.getLogger(DateUtils.class);

	/** @Description: DF_SEPARATE DF_YMD_SEPARATE DF_CLOSED: 时间格式转换 **/
	public static final ThreadLocal<DateFormat> DF_SEPARATE_YMDHM = new ThreadLocal<DateFormat>() {
		@Override
		protected DateFormat initialValue() {
			return new SimpleDateFormat("yyyy-MM-dd HH:mm");
		}
	};
	public static final ThreadLocal<DateFormat> DF_SEPARATE = new ThreadLocal<DateFormat>() {
		@Override
		protected DateFormat initialValue() {
			return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		}
	};
	public static final ThreadLocal<DateFormat> DF_SEPARATE_T = new ThreadLocal<DateFormat>() {
		@Override
		protected DateFormat initialValue() {
			return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
		}
	};
	public static final ThreadLocal<DateFormat> DF_SEPARATE_T_YMDHM = new ThreadLocal<DateFormat>() {
		@Override
		protected DateFormat initialValue() {
			return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm");
		}
	};
	public static final ThreadLocal<DateFormat> DF_SEPARATE_T_XXX = new ThreadLocal<DateFormat>() {
		@Override
		protected DateFormat initialValue() {
			return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
		}
	};
	public static final ThreadLocal<DateFormat> DF_SEPARATE_SSS = new ThreadLocal<DateFormat>() {
		@Override
		protected DateFormat initialValue() {
			return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
		}
	};
	public static final ThreadLocal<DateFormat> DF_SEPARATE_YMD = new ThreadLocal<DateFormat>() {
		@Override
		protected DateFormat initialValue() {
			return new SimpleDateFormat("yyyy-MM-dd");
		}
	};
	public static final ThreadLocal<DateFormat> DF_CLOSED = new ThreadLocal<DateFormat>() {
		@Override
		protected DateFormat initialValue() {
			return new SimpleDateFormat("yyyyMMddHHmmss");
		}
	};
	public static final ThreadLocal<DateFormat> DF_CLOSED_YMDHM = new ThreadLocal<DateFormat>() {
		@Override
		protected DateFormat initialValue() {
			return new SimpleDateFormat("yyyyMMddHHmm");
		}
	};
	public static final ThreadLocal<DateFormat> DF_CLOSED_YMD = new ThreadLocal<DateFormat>() {
		@Override
		protected DateFormat initialValue() {
			return new SimpleDateFormat("yyyyMMdd");
		}
	};
	public static final ThreadLocal<DateFormat> DF_CLOSED_YMD_HHMM = new ThreadLocal<DateFormat>() {
		@Override
		protected DateFormat initialValue() {
			return new SimpleDateFormat("yyyyMMdd_HHmm");
		}
	};
	public static final ThreadLocal<DateFormat> DF_Hm = new ThreadLocal<DateFormat>() {
		@Override
		protected DateFormat initialValue() {
			return new SimpleDateFormat("HH:mm");
		}
	};
	public static final ThreadLocal<DateFormat> DF_DD_MM_YYYY = new ThreadLocal<DateFormat>() {
		@Override
		protected DateFormat initialValue() {
			return new SimpleDateFormat("dd.MM.yyyy");
		}
	};
	public static final ThreadLocal<DateFormat> DF_SEPARATE_SLASH = new ThreadLocal<DateFormat>() {
		@Override
		protected DateFormat initialValue() {
			return new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
		}
	};
	public static final ThreadLocal<DateFormat> DF_SEPARATE_YMD_SLASH = new ThreadLocal<DateFormat>() {
		@Override
		protected DateFormat initialValue() {
			return new SimpleDateFormat("yyyy/MM/dd");
		}
	};

	public static final ThreadLocal<DateFormat> DF_SEPARATE_HH_MM_SLASH = new ThreadLocal<DateFormat>() {
		@Override
		protected DateFormat initialValue() {
			return new SimpleDateFormat("HH:mm");
		}
	};

	/** 根据日期获取星期几 */
	public static int getWeekByDay(Date date) {
		Calendar now = Calendar.getInstance();
		now.setTime(date);
		// 一周第一天是否为星期天
		boolean isFirstSunday = (now.getFirstDayOfWeek() == Calendar.SUNDAY);
		// 获取周几
		int weekDay = now.get(Calendar.DAY_OF_WEEK);
		// 若一周第一天为星期天，则-1
		if (isFirstSunday) {
			weekDay = weekDay - 1;
			if (weekDay == 0) {
				weekDay = 7;
			}
		}
		return weekDay;
	}

	/** 根据日期得到是今年的第几周 */
	public static int getWocheByDay(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setFirstDayOfWeek(Calendar.MONDAY);
		calendar.setTime(date);
		return calendar.get(Calendar.WEEK_OF_YEAR);
	}

	/**
	 *
	 * @description：-> 增加时间/减少时间
	 * 
	 * @param date
	 *            日期
	 * @param second
	 *            秒
	 * @param minute
	 *            分钟
	 * @param hours
	 *            小时
	 * @param days
	 *            天
	 * @param month
	 *            月
	 * @param year
	 *            年
	 * @return
	 *
	 * @作者：丶CHEN
	 * @时间：2017年5月16日 下午5:00:54 @版本：V1.0
	 *
	 */
	public static Date getAddorSubtractTimes(Date date, int second, int minute, int hours, int days, int month, int year) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.SECOND, second); // 秒
		calendar.add(Calendar.MINUTE, minute); // 分钟
		calendar.add(Calendar.HOUR_OF_DAY, hours);// 小时
		calendar.add(Calendar.DATE, days); // 天
		calendar.add(Calendar.MONTH, month);// 月
		calendar.add(Calendar.YEAR, year); // 年
		return calendar.getTime();
	}

	/**
	 * 
	 * @description：-> 得到date日期这个月所有weeks星期的集合
	 * 
	 * @param date
	 *            日期
	 * @param weeks
	 *            星期几的日期，多个用逗号隔开，例如 5,6,7
	 * @return list<map> week_星期的集合
	 *
	 * @作者：丶CHEN、 @时间：2018年6月20日 上午11:35:25、@版本：V1.0
	 */
	public static List<Map<String, Object>> getAllWeekByMonth(Date date, String weeks) {
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		// 时间转换
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		boolean weiterhin = true;
		int woche = getWocheByDay(date);
		int month = calendar.get(Calendar.MONTH);
		Map<String, Object> map = new HashMap<String, Object>();
		while (weiterhin) {
			calendar.add(Calendar.DATE, 1); // 天
			int woches = getWocheByDay(calendar.getTime());
			if (woche != woches) {
				woche = woches;
				if (map.size() > 1) {
					list.add(map);
				}
				map = new HashMap<String, Object>();
			}
			int week = getWeekByDay(calendar.getTime());
			if (weeks.contains(week + "")) {
				map.put("week_" + week, DF_SEPARATE.get().format(calendar.getTime()));
			}
			int months = calendar.get(Calendar.MONTH);
			if (month != months) {
				if (map.size() > 1) {
					list.add(map);
				}
				weiterhin = false;
			}
		}
		return list;
	}

	/**
	 * 
	 * @description：-> 得到date日期未来多少天所有weeks星期的集合
	 * 
	 * @param date
	 *            日期
	 * @param day
	 *            未来多少天
	 * @param weeks
	 *            星期几的日期，多个用逗号隔开，例如 5,6,7
	 * @return list<map> week_星期的集合
	 *
	 * @作者：丶CHEN、 @时间：2018年6月20日 下午1:33:50、@版本：V1.0
	 */
	public static List<Map<String, Object>> getAllWeekByDieZukunftDay(Date date, int day, String weeks) {
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		// 时间转换
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		int woche = getWocheByDay(date);
		Map<String, Object> map = new HashMap<String, Object>();
		for (int i = 1; i <= day; i++) {
			calendar.add(Calendar.DATE, 1); // 天
			int woches = getWocheByDay(calendar.getTime());
			if (woche != woches) {
				woche = woches;
				if (map.size() > 1) {
					list.add(map);
				}
				map = new HashMap<String, Object>();
			}
			int week = getWeekByDay(calendar.getTime());
			if (weeks.contains(week + "")) {
				map.put("week_" + week, DF_SEPARATE.get().format(calendar.getTime()));
			}
		}
		return list;
	}

	/**
	 * 
	 * @description：-> 得到客户端包含的星期的出发日期
	 * 
	 * @param weeks
	 *            包含的星期 0，1，2，3，4，5，6
	 * @param depTime
	 *            出发日期 2018-08-09
	 * @param returnTime
	 *            返程日期 2018-09-09
	 * @param minduration
	 *            停留几晚
	 * @return
	 *
	 * @作者：丶CHEN、 @时间：2018年7月12日 上午10:04:29、@版本：V1.0
	 */
	public static String getContainWeekGetDepartureWeek(String depTime, String returnTime, int minduration, String weeks) {
		try {
			int sWeek = Integer.parseInt(weeks.split(",")[0]);
			int eWeek = Integer.parseInt(weeks.split(",")[1]);
			if (eWeek == 0) {
				eWeek = 7;
			}
			if (minduration < eWeek - sWeek) {
				LOG.error("-DATE-minduration--小于包含星期之差-不满足条件-");
				return "";
			}
			Date depDate = DF_SEPARATE_YMD.get().parse(depTime);
			Date returnDate = DF_SEPARATE_YMD.get().parse(returnTime);
			long cha = returnDate.getTime() - depDate.getTime();
			int dayNum = (int) (cha / 1000 / 60 / 60 / 24) + 1;
			List<Map<String, Object>> weeksDay = getAllWeekByDieZukunftDay(depDate, dayNum, weeks);
			if (weeksDay == null || weeksDay.size() == 0) {
				LOG.error("-DATE-此段时间没有包含这个星期-");
				return "";
			}
			String result = "";
			// 时间转换
			Calendar calendar = Calendar.getInstance();
			calendar.setTime(depDate);
			for (int i = 0; i < dayNum - minduration; i++) {
				if (i != 0) {
					calendar.add(Calendar.DATE, 1); // 天
				}
				Date now = new Date(calendar.getTimeInMillis());
				int nWeek = getWeekByDay(now);
				Date end = getAddorSubtractTimes(now, 0, 0, 0, minduration, 0, 0);

				for (Map<String, Object> map : weeksDay) {
					if (!StringUtils.isEmpty(map.get("week_" + sWeek)) && !StringUtils.isEmpty(map.get("week_" + eWeek))) {
						Date week_sweek = DF_SEPARATE.get().parse(map.get("week_" + sWeek).toString());
						Date week_eweek = DF_SEPARATE.get().parse(map.get("week_" + eWeek).toString());
						if (now.getTime() <= week_sweek.getTime() && end.getTime() >= week_eweek.getTime()) {
							if (nWeek == 7) {
								nWeek = 0;
							}
							if (!result.contains(nWeek + "")) {
								result += nWeek + ",";
							}
						}
					}
				}
			}
			if (result.length() > 1) {
				result = result.substring(0, result.length() - 1);
			}
			return result;
		} catch (Exception e) {
			e.printStackTrace();
			return "";
		}
	}

	/**
	 * 
	 * @description：-> 由出生日期获得年龄
	 * 
	 * @param birthDay
	 * @return
	 *
	 * @作者：丶CHEN、 @时间：2018年8月10日 下午2:35:47、@版本：V1.0
	 */
	public static Integer getAge(Date birthDay) {
		try {
			Calendar cal = Calendar.getInstance();

			if (cal.before(birthDay)) {
				return 0;
			}
			int yearNow = cal.get(Calendar.YEAR);
			int monthNow = cal.get(Calendar.MONTH);
			int dayOfMonthNow = cal.get(Calendar.DAY_OF_MONTH);

			cal.setTime(birthDay);
			int yearBirth = cal.get(Calendar.YEAR);
			int monthBirth = cal.get(Calendar.MONTH);
			int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);

			int age = yearNow - yearBirth;

			if (monthNow <= monthBirth) {
				if (monthNow == monthBirth) {
					if (dayOfMonthNow < dayOfMonthBirth)
						age--;
				} else {
					age--;
				}
			}
			return age;
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * 
	 * @description：-> DF_SEPARATE_T转DF_SEPARATE 2018-11-02T10:40:00.000
	 * 
	 * @param time
	 * @return
	 *
	 * @作者：丶CHEN、 @时间：2018年10月30日 上午11:39:18、@版本：V1.0
	 */
	public static String getSeparateTime(String time) {
		try {
			return DF_SEPARATE.get().format(DF_SEPARATE_T.get().parse(time));
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * 
	 * @description：-> 返回几天
	 * 
	 * @param startTime
	 * @param endTime
	 * @return
	 *
	 * @作者：陳曉鬆
	 * @时间：2019年3月29日 下午5:42:49 @版本：V1.0
	 *
	 */
	public static Integer getDay(Date startTime, Date endTime) {
		return (int) ((endTime.getTime() - startTime.getTime()) / 1000 / 60 / 60 / 24) + 1;
	}

	/**
	 * @作者：陳曉鬆 @时间：2020年6月1日 下午2:55:06 @版本：V1.0 @description：-> 得到传入这个月的日历 date 日期 week 星期几 0-周日
	 */
	public static List<DateWeek> getMonthCalendar(String dateString) {
		List<DateWeek> list = null;
		try {
			Date date = DF_SEPARATE_YMD.get().parse(dateString);
			Calendar calendar = Calendar.getInstance();
			calendar.setTime(date);
			calendar.set(Calendar.DATE, 1);
			// 得到这个月的最后一天
			calendar.roll(Calendar.DATE, -1);
			int day = calendar.get(Calendar.DATE);

			list = new ArrayList<DateWeek>();
			for (int i = 1; i <= day; i++) {
				calendar.set(Calendar.DATE, i);
				DateWeek map = new DateWeek();
				map.setDate(DF_SEPARATE_YMD.get().format(calendar.getTime()));
				map.setWeek((calendar.get(Calendar.DAY_OF_WEEK) - 1));
				list.add(map);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return list;
	}

	/**
	 * @作者：陳曉鬆 @时间：2020年6月16日 下午1:54:48 @版本：V1.0 @description：->传入时间连续天数
	 */
	public static int continuityDay(Date date, List<Date> dateList) {
		/**当前 日期**/
		if (date == null) {
			return 0;
		}
		/**所有历史日期**/
		if (dateList == null || dateList.size() == 0) {
			return 1;
		}
		int continuityDay = 1;
		try {
			String nowDateFormat = DF_SEPARATE_YMD.get().format(date);
			Collections.sort(dateList);
			Calendar nowDate = Calendar.getInstance();
			nowDate.setTime(date);
			for (int i = dateList.size(); i > 0; i--) {
				if (DF_SEPARATE_YMD.get().format(dateList.get(i - 1)).contains(nowDateFormat)) {
					continue;
				}
				Calendar parseDateCalendar = Calendar.getInstance();
				parseDateCalendar.setTime(dateList.get(i - 1));
				if (dateList.get(i - 1).getTime() < date.getTime()) {// 满足条件
					if (nowDate.get(Calendar.DATE) - parseDateCalendar.get(Calendar.DATE) == 1) {
						continuityDay++;
						nowDate.setTime(dateList.get(i - 1));
					} else {
						break;
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return continuityDay;
	}
}
